package com.wenx.v3system.modular.cloud.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wenx.v3core.error.BusinessException;
import com.wenx.v3core.response.R;
import com.wenx.v3system.modular.cloud.domain.dto.UserAuthInfoDto;
import com.wenx.v3system.modular.cloud.domain.po.SysUser;
import com.wenx.v3system.modular.cloud.service.SysUserPermissionService;
import com.wenx.v3system.modular.cloud.service.SysUserRemoteService;
import com.wenx.v3system.modular.cloud.service.SysUserRestService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.Date;

import static cn.hutool.core.date.DateUtil.formatDate;

/**
 * 系统用户远程服务实现类
 * 基于Enhanced RBAC权限模型
 * 提供用户认证信息和权限查询服务，支持多种查询方式和缓存优化
 * 
 * @author wenx
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
// @DS(DynamicDataSourceConfig.DEFAULT_DATASOURCE)
public class SysUserRemoteServiceImpl implements SysUserRemoteService {

    // 缓存常量
    private static final String USER_AUTH_CACHE = "sys:user:auth";
    private static final String USER_PERMISSIONS_CACHE = "sys:user:permissions";
    private static final String USER_ROLES_CACHE = "sys:user:roles";
    private static final String USER_STATUS_CACHE = "sys:user:status";

    // 查询优先级常量
    private static final int PRIORITY_ACCOUNT = 1;
    private static final int PRIORITY_USERNAME = 2;
    private static final int PRIORITY_EMAIL = 3;
    private static final int PRIORITY_PHONE = 4;

    private final SysUserRestService userRestService;
    private final SysUserPermissionService userPermissionService;

    @Override
    @Cacheable(value = USER_AUTH_CACHE, key = "'identifier:' + #identifier")
    public R getUserAuthInfo(String identifier) {
        log.debug("根据标识符获取用户认证信息，标识符: {}", identifier);

        if (!StringUtils.hasText(identifier)) {
            throw new BusinessException("标识符不能为空");
        }

        // 按优先级顺序查询用户
        List<QueryStrategy> strategies = buildQueryStrategies(identifier);

        for (QueryStrategy strategy : strategies) {
            try {
                R result = strategy.execute();
                if (isSuccessResult(result)) {
                    log.debug("通过{}查询成功，标识符: {}", strategy.getDescription(), identifier);
                    return result;
                }
            } catch (Exception e) {
                log.warn("通过{}查询失败，标识符: {}, 错误: {}", strategy.getDescription(), identifier, e.getMessage());
            }
        }

        log.warn("用户不存在，标识符: {}", identifier);
        return R.failed("用户不存在");
    }

    @Override
    @Cacheable(value = USER_AUTH_CACHE, key = "'username:' + #username")
    public R getUserAuthInfoByUsername(String username) {
        log.debug("根据用户名获取用户认证信息，用户名: {}", username);
        
        return queryUserByField(username, "用户名", 
            wrapper -> wrapper.eq(SysUser::getUsername, username));
    }

    @Override
    @Cacheable(value = USER_AUTH_CACHE, key = "'account:' + #account")
    public R getUserAuthInfoByAccount(String account) {
        log.debug("根据账户名获取用户认证信息，账户名: {}", account);
        
        return queryUserByField(account, "用户名", 
            wrapper -> wrapper.and(w -> w.eq(SysUser::getUsername, account)
                          .or().eq(SysUser::getEmail, account)
                          .or().eq(SysUser::getPhone, account)));
    }

    @Override
    @Cacheable(value = USER_AUTH_CACHE, key = "'email:' + #email")
    public R getUserAuthInfoByEmail(String email) {
        log.debug("根据邮箱获取用户认证信息，邮箱: {}", email);
        
        return queryUserByField(email, "邮箱地址", 
            wrapper -> wrapper.eq(SysUser::getEmail, email));
    }

    @Override
    @Cacheable(value = USER_AUTH_CACHE, key = "'phone:' + #phone")
    public R getUserAuthInfoByPhone(String phone) {
        log.debug("根据手机号获取用户认证信息，手机号: {}", phone);
        
        return queryUserByField(phone, "手机号", 
            wrapper -> wrapper.eq(SysUser::getPhone, phone));
    }

    @Override
    @Cacheable(value = USER_PERMISSIONS_CACHE, key = "#userId")
    public R getUserPermissions(Long userId) {
        if (userId == null) {
            throw new BusinessException("用户ID不能为空");
        }
        
        Set<String> permissions = userPermissionService.getUserPermissions(userId);
        return R.ok(permissions);
    }

    @Override
    @Cacheable(value = USER_ROLES_CACHE, key = "#userId")
    public R getUserRoles(Long userId) {
        if (userId == null) {
            throw new BusinessException("用户ID不能为空");
        }
        
        Set<Long> roles = userPermissionService.getUserRoles(userId);
        return R.ok(roles);
    }

    @Override
    @Cacheable(value = USER_STATUS_CACHE, key = "#userId")
    public R isAccountActive(Long userId) {
        if (userId == null) {
            throw new BusinessException("用户ID不能为空");
        }
        
        SysUser user = userRestService.getById(userId);
        if (user == null) {
            return R.ok(false);
        }
        
        boolean isActive = ObjectUtil.equal(user.getStatus(), 1);
        return R.ok(isActive);
    }

    /**
     * 构建查询策略列表
     * 根据标识符特征确定查询优先级
     */
    private List<QueryStrategy> buildQueryStrategies(String identifier) {
        List<QueryStrategy> strategies = new ArrayList<>();
        
        // 优先级1: 账户名查询（支持多种登录方式）
        strategies.add(new QueryStrategy(PRIORITY_ACCOUNT, "账户名", 
            () -> getUserAuthInfoByAccount(identifier)));
        
        // 优先级2: 用户名精确查询
        strategies.add(new QueryStrategy(PRIORITY_USERNAME, "用户名", 
            () -> getUserAuthInfoByUsername(identifier)));
        
        // 优先级3: 邮箱查询（如果包含@符号）
        if (identifier.contains("@")) {
            strategies.add(new QueryStrategy(PRIORITY_EMAIL, "邮箱", 
                () -> getUserAuthInfoByEmail(identifier)));
        }
        
        // 优先级4: 手机号查询（如果是11位数字）
        if (identifier.matches("\\d{11}")) {
            strategies.add(new QueryStrategy(PRIORITY_PHONE, "手机号", 
                () -> getUserAuthInfoByPhone(identifier)));
        }
        
        // 按优先级排序
        strategies.sort(Comparator.comparingInt(QueryStrategy::getPriority));
        return strategies;
    }

    /**
     * 创建基础查询条件（只查询启用状态的用户）
     */
    private LambdaQueryWrapper<SysUser> createBaseQuery() {
        return new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getStatus, 1);
    }

    /**
     * 处理用户查询的通用逻辑
     */
    private R processUserQuery(LambdaQueryWrapper<SysUser> wrapper, String queryType, String queryValue) {
        SysUser user = userRestService.getOne(wrapper);
        if (user == null) {
            log.debug("未查询到用户，{}={}", queryType, queryValue);
            return R.failed("用户不存在");
        }

        UserAuthInfoDto authInfo = buildUserAuthInfo(user);
        return R.ok(authInfo);
    }


    private UserAuthInfoDto buildUserAuthInfo(SysUser user) {
        UserAuthInfoDto dto = new UserAuthInfoDto();
        BeanUtils.copyProperties(user, dto);

        dto.setAccount(user.getUsername());
        dto.setBirthday(formatDate(user.getBirthday()));
        dto.setEntryDate(formatDate(user.getEntryDate()));
        dto.setLastLoginTime(formatDate(user.getLastLoginTime()));
        dto.setPasswordExpireTime(formatDate(user.getPasswordExpireTime()));

        dto.setSuperAdmin("admin".equals(user.getUsername()) ? 1 : 0);

        boolean credentialsNonExpired = user.getPasswordExpireTime() == null
                || user.getPasswordExpireTime().after(new Date());
        dto.setCredentialsNonExpired(credentialsNonExpired);
        dto.setAccountNonExpired(credentialsNonExpired);
        dto.setAccountNonLocked(user.getStatus() != null && user.getStatus() == 1);
        dto.setEnabled(user.getStatus() != null && user.getStatus() == 1);

        dto.setPermissions(new HashSet<>());
        dto.setRoleIds(new HashSet<>());
        dto.setRoleCodes(new HashSet<>());
        dto.setRoleNames(new HashSet<>());
        dto.setDataScopeList(new HashSet<>());

        loadPermissionsAndRoles(user.getId(), dto);
        return dto;
    }


    /**
     * 加载用户权限和角色信息
     * 参考 PlatformUserRemoteInfraImpl 的实现，提供完整的权限和角色信息
     */
    private void loadPermissionsAndRoles(Long userId, UserAuthInfoDto dto) {
        try {
            Set<String> permissions = userPermissionService.getUserPermissions(userId);
            dto.setPermissions((permissions != null && !permissions.isEmpty())
                    ? permissions
                    : Set.of("ROLE_USER", "user:read"));
        } catch (Exception e) {
            log.warn("获取用户权限失败，使用默认权限，用户ID: {}", userId, e);
            dto.setPermissions(Set.of("ROLE_USER"));
        }

        try {
            Set<Long> roleIds = userPermissionService.getUserRoles(userId);
            dto.setRoleIds(roleIds != null ? roleIds : new HashSet<>());

            if (roleIds != null && !roleIds.isEmpty()) {
                Set<String> roleCodes = new HashSet<>();
                Set<String> roleNames = new HashSet<>();

                for (Long roleId : roleIds) {
                    if (roleId == 1L) {
                        roleCodes.add("ADMIN");
                        roleNames.add("管理员");
                    } else if (roleId == 2L) {
                        roleCodes.add("USER");
                        roleNames.add("普通用户");
                    } else {
                        roleCodes.add("ROLE_" + roleId);
                        roleNames.add("角色" + roleId);
                    }
                }

                dto.setRoleCodes(roleCodes);
                dto.setRoleNames(roleNames);
            }
        } catch (Exception e) {
            log.warn("获取用户角色失败，用户ID: {}", userId, e);
            dto.setRoleIds(new HashSet<>());
            dto.setRoleCodes(new HashSet<>());
            dto.setRoleNames(new HashSet<>());
        }

        try {
            Set<Long> dataScopeList = new HashSet<>();
            Long departmentId = dto.getDepartmentId();
            if (departmentId != null) {
                dataScopeList.add(departmentId);
                if (dto.getRoleIds() != null && dto.getRoleIds().contains(1L)) {
                    dataScopeList.clear(); // 管理员 = 全部权限
                }
            }
            dto.setDataScopeList(dataScopeList);
        } catch (Exception e) {
            log.warn("获取用户数据权限范围失败，用户ID: {}", userId, e);
            dto.setDataScopeList(new HashSet<>());
        }
    }
    
    /**
     * 判断结果是否成功
     */
    private boolean isSuccessResult(R result) {
        return result != null && ObjectUtil.equal(result.getCode(), 0L) && result.getData() != null;
    }
    
    /**
     * 通用的用户查询方法
     * 支持自定义查询条件和字段验证
     */
    private R queryUserByField(String value, String fieldName, 
            Function<LambdaQueryWrapper<SysUser>, LambdaQueryWrapper<SysUser>> queryBuilder) {
        if (!StringUtils.hasText(value)) {
            throw new BusinessException(fieldName + "不能为空");
        }

        LambdaQueryWrapper<SysUser> wrapper = queryBuilder.apply(createBaseQuery());
        return processUserQuery(wrapper, fieldName, value);
    }

    /**
     * 查询策略内部类
     * 封装查询优先级和执行逻辑
     */
    private static class QueryStrategy {
        private final int priority;
        private final String description;
        private final java.util.function.Supplier<R> executor;

        public QueryStrategy(int priority, String description, java.util.function.Supplier<R> executor) {
            this.priority = priority;
            this.description = description;
            this.executor = executor;
        }

        public int getPriority() {
            return priority;
        }

        public String getDescription() {
            return description;
        }

        public R execute() {
            return executor.get();
        }
    }
}